﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.ToolPositioningInternal.CApTPIContoursViewModel
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using EngineeringInternalExtension;
using EngineeringInternalExtension.AssemblyComponents.Refactoring;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.ToolPositioningInternal;

public class CApTPIContoursViewModel : INotifyPropertyChanged
{
  private string _updateButtonName;
  private bool _updateButtonEnabled;
  private bool _previewDecimatedContour;
  private bool _previewSaturatedContour;
  private bool _useAutoDecimation;
  private bool _previewContour;
  private bool _isGenerationInProgress;
  private string _destinationFileName;
  private int _maxNumberOfPoints;
  private int _selectedContourPointsNumber;
  private int _selectedContourDecimatedPointsNumber;
  private int _selectedContourSaturatedPointsNumber;
  private double _selectedContourBigRadius;
  private double _selectedContourSmallRadius;
  private double _decimatedContourEpsilon;
  private TxACGeometryExplorer _assemblyExplorer = new TxACGeometryExplorer();
  private CApTPIGraphicsDrawer _graphicsDrawer = new CApTPIGraphicsDrawer();
  private CApTPIContourManipulator _contourManipulator = new CApTPIContourManipulator();

  public CApTPIContoursViewModel()
  {
    this.ObjectsData = new ObservableCollection<CApTPILabelData>();
    this.LabelsData = new ObservableCollection<string>();
    this.AssemblyComponentData = new ObservableCollection<string>();
    this.UpdateButtonName = "Insert";
    this.MaxNumberOfPoints = 80 /*0x50*/;
    this.DecimatedContourEpsilon = 0.05;
    this.UseAutoDecimation = true;
    this._contourManipulator.NewContour += (Action<TxContour>) (c =>
    {
      if (!this.PreviewContour)
        return;
      Thread.Sleep(60);
      this.GraphicsDrawer.Clear();
      double pointSize = CApTPIContourManipulator.GetDistanceBetweenPoints(c.Center.Translation, c.FarthestPointFromCenter) / 80.0;
      this.GraphicsDrawer.DrawContour(c.Points, TxColor.TxColorBlue, c.Center.Translation, c.FarthestPointFromCenter, c.ClosestPointFromCenter, pointSize);
      TxApplication.RefreshDisplay();
    });
  }

  public ObservableCollection<CApTPILabelData> ObjectsData { get; set; }

  public ObservableCollection<string> LabelsData { get; set; }

  public ObservableCollection<string> AssemblyComponentData { get; set; }

  public CApTPILabelData SelectedRow { get; set; }

  public string DestinationFileName
  {
    get => this._destinationFileName;
    set
    {
      if (!(value != this._destinationFileName))
        return;
      this._destinationFileName = value;
      this.NotifyPropertyChanged(nameof (DestinationFileName));
    }
  }

  public bool AllowStop => this._isGenerationInProgress;

  public bool AllowStart => !this._isGenerationInProgress;

  public bool IsGenerationInProgress
  {
    get => this._isGenerationInProgress;
    set
    {
      if (this._isGenerationInProgress == value)
        return;
      this._isGenerationInProgress = value;
      this.NotifyPropertyChanged(nameof (IsGenerationInProgress));
      this.NotifyPropertyChanged("AllowStart");
      this.NotifyPropertyChanged("AllowStop");
    }
  }

  public bool PreviewContour
  {
    get => this._previewContour;
    set
    {
      if (value == this._previewContour)
        return;
      this._previewContour = value;
      this.NotifyPropertyChanged(nameof (PreviewContour));
      this.NotifyPropertyChanged("EnableDecimatedContourPreview");
      this.NotifyPropertyChanged("EnableSaturatedContourPreview");
      this.NotifyPropertyChanged("EnableAutoDecimation");
      this.NotifyPropertyChanged("UseAutoDecimation");
    }
  }

  public bool PreviewDecimatedContour
  {
    get => this._previewDecimatedContour;
    set
    {
      if (value == this._previewDecimatedContour)
        return;
      this._previewDecimatedContour = value;
      this.NotifyPropertyChanged(nameof (PreviewDecimatedContour));
      this.NotifyPropertyChanged("EnableAutoDecimation");
      this.NotifyPropertyChanged("UseAutoDecimation");
      this.NotifyPropertyChanged("EnableDecimatedContourPreview");
    }
  }

  public bool EnableDecimatedContourPreview => this.PreviewContour && this.PreviewDecimatedContour;

  public bool PreviewSaturatedContour
  {
    get => this._previewSaturatedContour;
    set
    {
      if (value == this._previewSaturatedContour)
        return;
      this._previewSaturatedContour = value;
      this.NotifyPropertyChanged(nameof (PreviewSaturatedContour));
      this.NotifyPropertyChanged("EnableSaturatedContourPreview");
    }
  }

  public bool EnableSaturatedContourPreview => this.PreviewContour && this.PreviewSaturatedContour;

  public bool UseAutoDecimation
  {
    get => this._useAutoDecimation;
    set
    {
      if (value == this._useAutoDecimation)
        return;
      this._useAutoDecimation = value;
      this.NotifyPropertyChanged(nameof (UseAutoDecimation));
      this.NotifyPropertyChanged("EnableAutoDecimation");
    }
  }

  public bool EnableAutoDecimation
  {
    get => this.PreviewContour && this.EnableDecimatedContourPreview && this.UseAutoDecimation;
  }

  public int MaxNumberOfPoints
  {
    get => this._maxNumberOfPoints;
    set
    {
      if (this._maxNumberOfPoints == value)
        return;
      this._maxNumberOfPoints = value;
      this.NotifyPropertyChanged(nameof (MaxNumberOfPoints));
    }
  }

  public bool UpdateButtonEnalbed
  {
    get => this._updateButtonEnabled;
    private set
    {
      if (this._updateButtonEnabled == value)
        return;
      this._updateButtonEnabled = value;
      this.NotifyPropertyChanged(nameof (UpdateButtonEnalbed));
    }
  }

  public double DecimatedContourEpsilon
  {
    get => this._decimatedContourEpsilon;
    set
    {
      if (this._decimatedContourEpsilon == value)
        return;
      this._decimatedContourEpsilon = value;
      this.NotifyPropertyChanged(nameof (DecimatedContourEpsilon));
    }
  }

  public int SelectedContourPointsNumber
  {
    get => this._selectedContourPointsNumber;
    set
    {
      if (value == this._selectedContourPointsNumber)
        return;
      this._selectedContourPointsNumber = value;
      this.NotifyPropertyChanged(nameof (SelectedContourPointsNumber));
    }
  }

  public int SelectedContourDecimatedPointsNumber
  {
    get => this._selectedContourDecimatedPointsNumber;
    set
    {
      if (value == this._selectedContourDecimatedPointsNumber)
        return;
      this._selectedContourDecimatedPointsNumber = value;
      this.NotifyPropertyChanged(nameof (SelectedContourDecimatedPointsNumber));
    }
  }

  public int SelectedContourSaturatedPointsNumber
  {
    get => this._selectedContourSaturatedPointsNumber;
    set
    {
      if (value == this._selectedContourSaturatedPointsNumber)
        return;
      this._selectedContourSaturatedPointsNumber = value;
      this.NotifyPropertyChanged(nameof (SelectedContourSaturatedPointsNumber));
    }
  }

  public double SelectedContourBigRadius
  {
    get => this._selectedContourBigRadius;
    set
    {
      if (value == this._selectedContourBigRadius)
        return;
      this._selectedContourBigRadius = value;
      this.NotifyPropertyChanged(nameof (SelectedContourBigRadius));
    }
  }

  public double SelectedContourSmallRadius
  {
    get => this._selectedContourSmallRadius;
    set
    {
      if (value == this._selectedContourSmallRadius)
        return;
      this._selectedContourSmallRadius = value;
      this.NotifyPropertyChanged(nameof (SelectedContourSmallRadius));
    }
  }

  public string UpdateButtonName
  {
    get => this._updateButtonName;
    set
    {
      if (!(this._updateButtonName != value))
        return;
      this._updateButtonName = value;
      this.NotifyPropertyChanged(nameof (UpdateButtonName));
    }
  }

  public void RefreshButtonState(int selectedItemsCount, int selectedObjects)
  {
    if (selectedObjects > 0)
    {
      this.UpdateButtonName = "Insert";
      this.UpdateButtonEnalbed = true;
    }
    else if (selectedItemsCount > 0)
    {
      this.UpdateButtonName = "Update";
      this.UpdateButtonEnalbed = true;
    }
    else
      this.UpdateButtonEnalbed = false;
  }

  public CApTPIGraphicsDrawer GraphicsDrawer => this._graphicsDrawer;

  public void StartGenerate()
  {
    this.IsGenerationInProgress = true;
    if (string.IsNullOrEmpty(this.DestinationFileName))
    {
      int num = (int) System.Windows.MessageBox.Show("Please provide a 'Destination:' file path", "Missing destination file", MessageBoxButton.OK, MessageBoxImage.Exclamation);
    }
    else
    {
      TxApplication.ActiveDocument.Selection.Clear();
      try
      {
        Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
        using (StreamWriter csv = new StreamWriter(this.DestinationFileName, true))
        {
          this.WriteHeaderLine(csv);
          foreach (CApTPILabelData capTpiLabelData in (Collection<CApTPILabelData>) this.ObjectsData)
          {
            List<TxContour> contours = this.GenerateObject(capTpiLabelData);
            this.ContoursToCsv(csv, capTpiLabelData, contours);
          }
        }
      }
      finally
      {
        this.IsGenerationInProgress = false;
        Mouse.OverrideCursor = (System.Windows.Input.Cursor) null;
      }
    }
  }

  private void WriteHeaderLine(StreamWriter csv)
  {
    if (csv?.BaseStream == null || csv == null || csv.BaseStream.Position != 0L)
      return;
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.Append("Type, ");
    for (int index = 1; index < this.MaxNumberOfPoints; ++index)
      stringBuilder.Append($"P_X{index}, P_Y{index}, P_Z{index}, ");
    stringBuilder.Append($"P_X{this.MaxNumberOfPoints}, P_Y{this.MaxNumberOfPoints}, P_Z{this.MaxNumberOfPoints}");
    csv.WriteLine((object) stringBuilder);
  }

  private void ContoursToCsv(StreamWriter csv, CApTPILabelData labelData, List<TxContour> contours)
  {
    foreach (TxContour contour in contours)
    {
      List<TxVector> points = CApTPIContourManipulator.ScaleContour(contour.Points);
      if (points.Count > this.MaxNumberOfPoints)
      {
        int num = (int) System.Windows.MessageBox.Show($"{labelData.Object.Name} contour in depth {labelData.ContourDepth} has {points.Count} points which exceeds the MaxNumOfPoints parameter of {this.MaxNumberOfPoints}", "Limit exceeded", MessageBoxButton.OK, MessageBoxImage.Exclamation);
        break;
      }
      string str1 = CApTPIContourManipulator.ConvertContourPointsToString(points, this.MaxNumberOfPoints);
      string str2 = $"{labelData.Label},{str1}";
      csv.WriteLine(str2);
    }
  }

  public void StopGenerate()
  {
    if (this._contourManipulator.IsManipulationInProgress)
      this._contourManipulator.IsManipulationInProgress = false;
    this.IsGenerationInProgress = false;
  }

  public event PropertyChangedEventHandler PropertyChanged;

  private void NotifyPropertyChanged(string propertyName)
  {
    PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
    if (propertyChanged == null)
      return;
    propertyChanged((object) this, new PropertyChangedEventArgs(propertyName));
  }

  public void ShowContour(CApTPILabelData lableData)
  {
    ITxACComponent assemblyComp;
    if (lableData.Contours == null && this.ExploreComponent(lableData, out assemblyComp))
    {
      lableData.Contours = new List<TxContour>();
      if (assemblyComp.EndEffectors != null && assemblyComp.EndEffectors.Count > 0)
      {
        lableData.Contours.AddRange((IEnumerable<TxContour>) assemblyComp.EndEffectors[0].ShapeContours);
        if (assemblyComp.EndEffectors[0].ShapeContours.Count > 0)
          this.SelectedContourPointsNumber = assemblyComp.EndEffectors[0].ShapeContours[0].Points.Count;
      }
      ((IDisposable) assemblyComp).Dispose();
    }
    if (lableData.Contours == null)
      return;
    foreach (TxContour contour in lableData.Contours)
    {
      List<TxVector> points = new List<TxVector>((IEnumerable<TxVector>) contour.Points);
      points = CApTPIContourManipulator.MakeCloseContour(points);
      this.SelectedContourPointsNumber = points.Count;
      List<TxVector> txVectorList = points;
      this.SelectedContourSaturatedPointsNumber = 0;
      if (this.EnableSaturatedContourPreview && points.Count < this.MaxNumberOfPoints)
      {
        txVectorList = CApTPIContourManipulator.SaturatePolyline(points, contour.Length / (double) this.MaxNumberOfPoints, this.MaxNumberOfPoints);
        this.SelectedContourSaturatedPointsNumber = txVectorList.Count;
      }
      double closestDist;
      TxVector fromContourCenter1 = CApTPIContourManipulator.FindClosestContourPointFromContourCenter(contour.Center.Translation, txVectorList, out closestDist);
      this.SelectedContourSmallRadius = Math.Round(closestDist, 5);
      double farthestDist;
      TxVector fromContourCenter2 = CApTPIContourManipulator.FindFarthestContourPointFromContourCenter(contour.Center.Translation, txVectorList, out farthestDist);
      this.SelectedContourBigRadius = Math.Round(farthestDist, 5);
      double pointSize = this.SelectedContourBigRadius / 80.0;
      TxManipulator manip = this._graphicsDrawer.DrawContour(points, TxColor.TxColorRed, contour.Center.Translation, fromContourCenter2, fromContourCenter1, pointSize);
      if (this.EnableSaturatedContourPreview)
      {
        List<TxVector> list1 = txVectorList.Where<TxVector>((Func<TxVector, bool>) (i => TxVector.op_Equality(points.Find((Predicate<TxVector>) (o => TxVector.op_Equality(o, i))), (TxVector) null))).ToList<TxVector>();
        List<TxVector> list2 = txVectorList.Where<TxVector>((Func<TxVector, bool>) (i => TxVector.op_Inequality(points.Find((Predicate<TxVector>) (o => TxVector.op_Equality(o, i))), (TxVector) null))).ToList<TxVector>();
        this._graphicsDrawer.DrawContourPoints(manip, list1, TxColor.TxColorWhite, pointSize / 1.1);
        this._graphicsDrawer.DrawContourPoints(manip, list2, TxColor.TxColorBlack, pointSize / 1.1);
      }
      if (this.EnableDecimatedContourPreview)
      {
        if (this.UseAutoDecimation)
        {
          double epsilon;
          points = CApTPIContourManipulator.DecimatePolyline(points, this.MaxNumberOfPoints, out epsilon);
          this.DecimatedContourEpsilon = Math.Round(epsilon, 5);
        }
        else
          points = CApTPIContourManipulator.DecimatePolyline(points, this.DecimatedContourEpsilon);
        this._graphicsDrawer.DrawContour(points, TxColor.TxColorBlue, contour.Center.Translation, contour.FarthestPointFromCenter, contour.ClosestPointFromCenter, pointSize);
        this.SelectedContourDecimatedPointsNumber = points.Count;
      }
      TxApplication.RefreshDisplay();
    }
  }

  private List<TxContour> GenerateObject(CApTPILabelData lableData)
  {
    List<TxContour> txContourList1 = new List<TxContour>();
    if (lableData.Contours == null)
    {
      ITxACComponent assemblyComp;
      if (this.ExploreComponent(lableData, out assemblyComp))
      {
        if (assemblyComp.EndEffectors != null && assemblyComp.EndEffectors.Count > 0)
          txContourList1.AddRange((IEnumerable<TxContour>) assemblyComp.EndEffectors[0].ShapeContours);
        ((IDisposable) assemblyComp).Dispose();
      }
    }
    else
      txContourList1.AddRange((IEnumerable<TxContour>) lableData.Contours);
    List<TxContour> txContourList2 = new List<TxContour>();
    foreach (TxContour txContour1 in txContourList1)
    {
      TxContour txContour2 = new TxContour(txContour1);
      txContour2.Center = new TxTransformation(new TxVector(), new TxVector(), (TxTransformation.TxRotationType) 1);
      List<TxVector> polyline = CApTPIContourManipulator.MakeCloseContour(txContour2.Points);
      if (polyline.Count < this.MaxNumberOfPoints)
        polyline = CApTPIContourManipulator.SaturatePolyline(polyline, txContour2.Length / (double) this.MaxNumberOfPoints, this.MaxNumberOfPoints);
      else if (this.UseAutoDecimation && polyline.Count > this.MaxNumberOfPoints)
        polyline = CApTPIContourManipulator.DecimatePolyline(polyline, this.MaxNumberOfPoints, out double _);
      this._contourManipulator.Contour = new TxContour(polyline, true);
      this._contourManipulator.CreateContours(lableData.NumberOfContours);
      txContourList2.AddRange((IEnumerable<TxContour>) this._contourManipulator.Contours);
    }
    return txContourList2;
  }

  private bool ExploreComponent(CApTPILabelData lableData, out ITxACComponent assemblyComp)
  {
    bool flag = false;
    assemblyComp = (ITxACComponent) null;
    string str = string.Empty;
    try
    {
      if (lableData.Object != null)
      {
        if (this._assemblyExplorer.Explore(lableData.Object as ITxComponent, lableData.AssemblyComponentType, lableData.IsTool, lableData.ContourDepth, ref assemblyComp))
          flag = true;
      }
    }
    catch (TxAssemblyComponentsCannotReadGeometryException ex)
    {
      str = "Cannot ready component geometry";
    }
    catch (TxUnknownErrorException ex)
    {
      str = ((Exception) ex).Message;
    }
    catch (TxException ex)
    {
      str = ((Exception) ex).Message;
    }
    finally
    {
      if (!string.IsNullOrEmpty(str))
      {
        int num = (int) TxMessageBox.Show($"{lableData.Object.Name}: {str}", "Contours Generation Command", MessageBoxButtons.OK, MessageBoxIcon.Hand);
      }
    }
    return flag;
  }

  public void ClearData() => this.GraphicsDrawer.Clear();
}
